home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / modula2 / modprint / modprint.mod < prev    next >
Encoding:
Text File  |  1994-09-22  |  17.6 KB  |  646 lines

  1. MODULE ModPrint;
  2.  
  3. (*
  4.  * This program is a utility to print Modula-2 programs with 
  5.  * pagination, expanded tabs, and emboldened keywords.  It should be 
  6.  * easy to modify the keyword list to search for other keywords if desired.
  7.  * 
  8.  * The keyword emboldening works with Epson compatible printers.  It
  9.  * should be fairly simple to change it to work with other types
  10.  * of printers.
  11.  *
  12.  * USAGE :
  13.  *     modprint [-noh][-nok][-nop][-p #][-l][-?][-x #][-w #][<filenames>]
  14.  *        -noh    : disables header printing.
  15.  *        -nok    : disables keyword emboldening.
  16.  *        -nop    : disables pagination.
  17.  *        -p    : Sets pagelength.  Default is 66.
  18.  *        -l    : use Near Letter Quality printing    
  19.  *        -?    : prints usage line
  20.  *        -x    : Sets tab expansion size.  Default is 8.
  21.  *         -w      : Sets line width. Default is 80 characters.
  22.  *
  23.  *    The follwing are the defaults:
  24.  *        Use draft print mode.
  25.  *            Tab stops are set every 8 spaces.
  26.  *        Page length is 66.
  27.  *        Line width is 80 chars.
  28.  *        Stdin is the input. 
  29.  *
  30.  *    Copyright 1987, Barry Locklear
  31.  *
  32.  *    The author grants the privilege of distributing this
  33.  *    software free, or for a nominal charge to cover the media
  34.  *    costs, or for connect time.  
  35.  *
  36.  *    Distribution for commercial gain is prohibited.
  37.  *    The only exception is that Jefferson Software may
  38.  *    distribute it with their Modula-2 package if they so
  39.  *    desire.
  40.  *
  41.  *    If improvements are made, please send them to me.
  42.  *    Compuserve: 76327,2102
  43.  *    Genie:      BLOCKLEAR
  44.  *      The Jefferson Software BBS (602)276-6102
  45.  *
  46.  *    This version of ModPrint is written in Jefferson Software Modula-2
  47.  *)
  48.  
  49. (*
  50.  * Author: Barry Locklear 12/07/87
  51.  * Version # 1.0
  52.  *)
  53.  
  54. (* IMPORTED CONSTs *)
  55. FROM FileSystem IMPORT MAXPATHLEN;
  56. FROM ASCII     IMPORT HT, LF;
  57.  
  58. (* IMPORTED TYPEs *)
  59. FROM FileSystem IMPORT File, Response;
  60. FROM String     IMPORT CompareResults;
  61. FROM DateTime   IMPORT DateType, TimeType, DateFormat, TimeFormat;
  62.  
  63. (* IMPORTED VARs *)
  64. FROM InOut    IMPORT in, out, Done;
  65.  
  66. (* IMPORTED PROCEDUREs *)
  67. FROM BasePage     IMPORT NumberOfArguments, GetArgument;
  68. FROM GEMDOSTimeDate IMPORT Tgetdate, Tgettime;
  69. FROM DateTime    IMPORT GetDate, GetTime;
  70. FROM HashTable  IMPORT InsertElem, LookupElem;
  71. FROM FileSystem IMPORT Lookup, Again;
  72. FROM InOut     IMPORT CloseInput, CloseOutput, Read, Write, WriteString, 
  73.                WriteLn, WriteCard;
  74. FROM SYSTEM     IMPORT ADDRESS, TSIZE, SHIFT;
  75. FROM Heap     IMPORT CreateHeap;
  76. FROM String     IMPORT InitStringModule, Assign, Compare, GetTerminator;
  77. FROM System    IMPORT UserDebug;
  78.  
  79. IMPORT Terminal;
  80.  
  81. CONST
  82.  HEAPSIZE = 5000;    (* Size of heap that program uses *)
  83.  
  84. VAR
  85.   HeaderFlag,        (* TRUE -> Print headers *)
  86.   KeyWordFlag,      (* TRUE -> Embolden keywords *)
  87.   PageFlag,        (* TRUE -> Paginate the output *)
  88.   DraftFlag,        (* TRUE -> Print draft output *)
  89.   FinishedFile,        (* TRUE -> Finished printing file *)
  90.   InComment,         (* TRUE -> We are inside of a comment *)
  91.   InString : BOOLEAN;    (* TRUE -> We are inside of a string constant *)
  92.  
  93.   DateString : DateType;(* Contains date string - updated for each file *)
  94.   TimeString : TimeType;(* Contains time string - updated for each file *)
  95.  
  96.   NumArgs,        (* Number of arguments passed in *)
  97.   ArgIndex,        (* Current index into argument array *)
  98.   CharCount,         (* Number of characters on this line *)
  99.   LineCount,        (* Number of lines printed this page *)
  100.   PageCount,        (* Number of pages printed *)
  101.   TabSize,        (* Tab expansion size *)
  102.   MaxLineSize,        (* Maximum characters on a line *)
  103.   PageSize,        (* Lines per page *)
  104.   FooterSize : CARDINAL;(* Blank size at bottom of page *)
  105.  
  106.   StringTerminator : CHAR;
  107.  
  108.   ArgString : ARRAY [0..MAXPATHLEN] OF CHAR; (* Current Argument *)
  109.  
  110. (* --------------------------------------------------------------------*)
  111.  
  112. (* 
  113.  * Initialize the hash table with the lookup values
  114.  *)
  115. PROCEDURE InitHashTable() : BOOLEAN;
  116. BEGIN
  117.  (* fill the table up *)
  118.  InsertElem("AND");    InsertElem("ARRAY");    InsertElem("BEGIN");
  119.  InsertElem("BY");    InsertElem("CASE");    InsertElem("CONST");
  120.  InsertElem("DEFINITION"); InsertElem("DIV");    InsertElem("DO");
  121.  InsertElem("ELSE");    InsertElem("ELSIF");    InsertElem("END");
  122.  InsertElem("FROM");    InsertElem("FOR");    InsertElem("IF");
  123.  InsertElem("IMPLEMENTATION");    InsertElem("IMPORT");    InsertElem("IN");
  124.  InsertElem("LOOP");    InsertElem("MOD");    InsertElem("MODULE");
  125.  InsertElem("NOT");    InsertElem("OF");    InsertElem("OR");
  126.  InsertElem("POINTER");    InsertElem("PROCEDURE");InsertElem("QUALIFIED");
  127.  InsertElem("RECORD");    InsertElem("REPEAT");    InsertElem("RETURN");
  128.  InsertElem("SET");    InsertElem("THEN");    InsertElem("TO");
  129.  InsertElem("TYPE");    InsertElem("UNTIL");    InsertElem("VAR");
  130.  InsertElem("WHILE");    InsertElem("WITH");    InsertElem("CARDINAL");
  131.  InsertElem("LONGCARD");InsertElem("INTEGER");    InsertElem("LONGINT");
  132.  InsertElem("BYTE");    InsertElem("WORD");    InsertElem("LONGWORD");
  133.  InsertElem("ADDRESS");    InsertElem("BOOLEAN");    InsertElem("CHAR");
  134.  
  135.  RETURN TRUE;
  136. END InitHashTable;
  137.  
  138. (* --------------------------------------------------------------------*)
  139.  
  140. (*
  141.  * This is some code for a String to Cardinal routine.
  142.  * It takes a string in decimal format and converts it to a Cardinal.
  143.  * It returns FALSE if the routine fails, TRUE if it works.
  144.  *)
  145. PROCEDURE StrToCard( NumString: ARRAY OF CHAR; VAR Card: CARDINAL ): BOOLEAN;
  146.  VAR
  147.   index,
  148.   limit : CARDINAL;
  149. BEGIN
  150.  limit := HIGH( NumString );
  151.  Card := 0;
  152.  
  153.  FOR index := 0 TO limit DO
  154.  
  155.   IF NumString[index] = StringTerminator THEN RETURN TRUE; END; (* IF *)
  156.  
  157.   IF (NumString[index] >= '0') AND (NumString[index] <= '9') THEN
  158.     Card := ( Card * 10 ) + VAL( CARDINAL, ORD( NumString[index] ))
  159.              - VAL( CARDINAL, ORD( '0' ));
  160.   ELSE RETURN FALSE;
  161.   END; (* IF *)
  162.  END; (* FOR *)
  163.  
  164.  RETURN TRUE;
  165.  
  166. END StrToCard;
  167.  
  168. (* --------------------------------------------------------------------*)
  169.  
  170. (*
  171.  * Global initializations take place here
  172.  *)
  173. PROCEDURE GlobalInit() : BOOLEAN;
  174. BEGIN
  175.   (*
  176.    * Open the printer for use later
  177.    *)
  178.  
  179.   IF out.res = done THEN
  180.     Assign( out.name, "PRN:");
  181.     Lookup( out, out.name, TRUE);
  182.   END; (* IF *)
  183.  
  184.   IF out.res # done THEN 
  185.      Done := FALSE;
  186.      Terminal.WriteString("Could not open printer for writing!");
  187.      Terminal.WriteLn;
  188.      RETURN FALSE;
  189.   ELSE
  190.      Done := TRUE;    
  191.   END; (* IF *)
  192.  
  193.   (* 
  194.    * Make sure we have some space to ALLOCATE from later
  195.    *)
  196.   IF NOT CreateHeap( HEAPSIZE, TRUE ) THEN RETURN FALSE; END; (* IF *)
  197.  
  198.   (*
  199.    * Initialize the string handling module
  200.    *)
  201.   InitStringModule;
  202.  
  203.   (* 
  204.    * Initialize the globals.
  205.    *)
  206.   HeaderFlag  := TRUE;    (* Print Headers *)
  207.   KeyWordFlag := TRUE;    (* Print Keywords *)
  208.   PageFlag    := TRUE;    (* Paginate Output *)
  209.   DraftFlag   := TRUE;    (* Print draft quality *)
  210.  
  211.   TabSize     := 8;    (* Set default tabsize *)
  212.   PageSize    := 66;    (* Set default pagesize *)
  213.   MaxLineSize := 80;    (* Default to 80 chars/line *)
  214.   FooterSize  := 4;    (* blank lines after pagenumber *)
  215.  
  216.   NumArgs     := NumberOfArguments();
  217.   ArgIndex    := 1;
  218.  
  219.   StringTerminator := GetTerminator();
  220.  
  221.   RETURN InitHashTable();
  222.     
  223. END GlobalInit;
  224.  
  225. (* --------------------------------------------------------------------*)
  226.  
  227. PROCEDURE PrintUsage();
  228. BEGIN
  229.  CloseOutput();    (* make sure that output goes to terminal *)
  230.  WriteString("USAGE: modprint [options][<filenames>]"); WriteLn;
  231.  WriteString("Options are:"); WriteLn;
  232.  WriteString("   -noh: disables header printing"); WriteLn;
  233.  WriteString("   -nok: disables keyword emboldening"); WriteLn;
  234.  WriteString("   -nop: disables pagination"); WriteLn;
  235.  WriteString("   -p #: set page length to # lines. Default is 66"); WriteLn;
  236.  WriteString("   -l  : use Near Letter Quality print"); WriteLn;
  237.  WriteString("   -?  : prints usage line and exits"); WriteLn;
  238.  WriteString("   -x #: Sets tab expansion size to #. Default is 8"); WriteLn;
  239.  WriteString("   -w #: Sets line width.  Default is 80 characters"); WriteLn;
  240.  WriteString("NOTE: standard input (stdin) is used if no filenames are given"); 
  241.  WriteLn;
  242. END PrintUsage;
  243.  
  244. (* --------------------------------------------------------------------*)
  245.  
  246. PROCEDURE GetArgs() : BOOLEAN;
  247. BEGIN
  248.  ArgIndex := 0;
  249.  
  250.  LOOP
  251.    INC( ArgIndex );
  252.    GetArgument( ArgIndex, ArgString );
  253.    IF ArgString[0] # '-' THEN EXIT END;
  254.    
  255.    (* Take action on the argument *)
  256.    CASE ArgString[1] OF
  257.      'n' : IF Compare( ArgString, "-noh" ) = Equal THEN 
  258.         HeaderFlag := FALSE;
  259.            ELSIF Compare( ArgString, "-nok" ) = Equal THEN 
  260.         KeyWordFlag := FALSE;
  261.        ELSIF Compare( ArgString, "-nop" ) = Equal THEN 
  262.         PageFlag := FALSE;
  263.            ELSE PrintUsage();
  264.         RETURN FALSE;
  265.        END;
  266.     
  267.    | 'l' : DraftFlag := FALSE;
  268.            
  269.    | 'p' : INC( ArgIndex );
  270.            GetArgument( ArgIndex, ArgString );
  271.            IF NOT StrToCard( ArgString, PageSize ) THEN 
  272.         PrintUsage();
  273.                 RETURN FALSE;
  274.        END; (* IF *)
  275.  
  276.    | 'x' : INC( ArgIndex );
  277.            GetArgument( ArgIndex, ArgString );
  278.            IF NOT StrToCard( ArgString, TabSize ) THEN 
  279.         PrintUsage();
  280.         RETURN FALSE;
  281.        END; (* IF *)
  282.  
  283.    | 'w' : INC( ArgIndex );
  284.        GetArgument( ArgIndex, ArgString );
  285.        IF NOT StrToCard( ArgString, MaxLineSize ) THEN 
  286.         PrintUsage();
  287.         RETURN FALSE;
  288.        END; (* IF *)
  289.  
  290.    ELSE PrintUsage();
  291.         RETURN FALSE;
  292.    END; (* CASE *)
  293.  END; (* END LOOP *)
  294.  
  295.  IF ArgIndex > NumArgs THEN 
  296.     Terminal.WriteString("Error in argument list!"); WriteLn;
  297.     RETURN FALSE;
  298.  ELSE RETURN TRUE;
  299.  END; (* IF *)
  300.  
  301. END GetArgs;
  302.  
  303. (* --------------------------------------------------------------------*)
  304.  
  305. PROCEDURE PerFileInit();
  306. BEGIN
  307.  
  308.  GetDate( DateString, MoDayYear );
  309.  GetTime( TimeString, Hour24 );
  310.  
  311.  IF DraftFlag THEN 
  312.     (* Set printer in draft mode *)
  313.     Write( CHR(27) );
  314.     Write( CHR(120) );
  315.     Write( CHR(0) );
  316.  ELSE (* Set printer to Near Letter Quality Mode *)
  317.     Write( CHR(27) );
  318.     Write( CHR(120) );
  319.     Write( CHR(1) );
  320.  END; (* IF *)
  321.  
  322.  InString    := FALSE;    (* We don't start out in a string *)
  323.  InComment   := FALSE;    (* We don't start out in a comment *)
  324.  
  325.  CharCount   := 0;    (* No chars printed yet *)
  326.  LineCount   := 1;    (* Start on line 1 *)
  327.  PageCount   := 0;    (* No pages printed yet *)
  328.  FinishedFile := FALSE; (* We're just starting! *)
  329. END PerFileInit;
  330.  
  331. (* --------------------------------------------------------------------*)
  332.  
  333. PROCEDURE PrintHeader( PageNo: CARDINAL ): CARDINAL;
  334.  
  335. BEGIN
  336.  WriteLn;
  337.  WriteLn;
  338.  
  339.  IF NOT HeaderFlag THEN
  340.     RETURN 2;
  341.  ELSE
  342.     (*
  343.      * Print Date and Time
  344.      *)
  345.     WriteString( "  " );
  346.     WriteString( DateString );
  347.     WriteString("  ");
  348.     WriteString( TimeString );
  349.  
  350.     (*
  351.      * Print file name if there is one
  352.      *)
  353.     IF in.handle # 0 THEN
  354.     (* We have a file *)
  355.     WriteString("             ");
  356.     WriteString(ArgString);
  357.     ELSE
  358.     (* We have stdin *)    
  359.     WriteString("                          ");
  360.     END; (* IF *)
  361.  
  362.     (*
  363.      * Print Page Number
  364.      *)
  365.     WriteString("                     Page:");
  366.     WriteCard( PageNo, 2 );
  367.     WriteLn;
  368.     WriteLn;
  369.     WriteLn;
  370.     RETURN 5;
  371.  END; (* IF *)
  372. END PrintHeader;
  373.  
  374. (* --------------------------------------------------------------------*)
  375.  
  376. PROCEDURE NewPage();
  377. BEGIN
  378.  INC( PageCount );
  379.  LineCount := PrintHeader( PageCount ) + 1;
  380. END NewPage;
  381.  
  382. (* --------------------------------------------------------------------*)
  383.  
  384. PROCEDURE NewLine();
  385.  VAR
  386.   i : CARDINAL;
  387.  
  388. BEGIN
  389.  Write( LF );
  390.  CharCount := 0;
  391.  INC( LineCount );
  392.  
  393.  IF PageFlag THEN
  394.     IF LineCount >= (PageSize - FooterSize) THEN 
  395.  
  396.     FOR i := LineCount TO PageSize DO 
  397.         Write( LF ); 
  398.     END; (* FOR *)
  399.  
  400.     IF ~FinishedFile THEN
  401.        NewPage();
  402.     END; (* IF *) 
  403.     END; (* IF *)
  404.  END; (* IF *)
  405. END NewLine;
  406.  
  407. (* --------------------------------------------------------------------*)
  408.  
  409. PROCEDURE PrintChar( InChar: CHAR );
  410. BEGIN
  411.  IF( InChar = LF ) THEN
  412.     NewLine();
  413.  ELSE 
  414.     IF CharCount >= MaxLineSize THEN NewLine(); END; (* IF *)
  415.  
  416.     Write( InChar );
  417.     INC( CharCount );
  418.  END; (* IF *)
  419. END PrintChar;
  420.  
  421. (* --------------------------------------------------------------------*)
  422.  
  423. (*
  424.  * PrintToken
  425.  *  Prints tokens, emboldening if necessary.  This works for EPSON
  426.  *  compatible printers.  Should be easy to change for others.
  427.  *)
  428. PROCEDURE PrintToken( Token: ARRAY OF CHAR; TokenLen: CARDINAL );
  429.  VAR
  430.   i        : CARDINAL;
  431.   emBolden : BOOLEAN;
  432.  
  433. BEGIN
  434.   emBolden := FALSE;
  435.  (* 
  436.   * See if the token would be split up at the end of a line.
  437.   * If so, then start a new line.
  438.   *)
  439.  IF ( CharCount + TokenLen ) > MaxLineSize THEN NewLine(); END; (* IF *)
  440.  
  441.  (*
  442.   * If not in a comment or a string and we are to embolden keywords, 
  443.   * check to see if we should embolden the token.
  444.   *)
  445.  IF NOT( InComment OR InString ) AND KeyWordFlag THEN
  446.     emBolden := LookupElem( Token );
  447.     IF emBolden THEN 
  448.     (* Put printer in BOLD font *)
  449.     Write( CHR(27) );    (* ESC *)
  450.     Write( 'E' );        (* BOLD *)
  451.     END; (* IF *)
  452.  END; (* IF *)
  453.  
  454.  FOR i := 0 TO TokenLen-1 DO PrintChar( Token[i] ); END; (* FOR *)
  455.  
  456.  IF emBolden THEN 
  457.     (* Take printer out of bold mode *)
  458.     Write( CHR(27) );    (* ESC *)
  459.     Write( 'F' );    (* NO BOLD *)
  460.  END; (* IF *)
  461.  
  462. END PrintToken;
  463.  
  464. (* --------------------------------------------------------------------*)
  465.  
  466. PROCEDURE PrintAFile();
  467.  VAR
  468.   tokenIndex,
  469.   i        : CARDINAL;
  470.  
  471.   commentLevel : CARDINAL;        (* Level of nesting in comments *)
  472.  
  473.   inChar,
  474.   stringChar: CHAR;
  475.  
  476.   token     : ARRAY [0..127] OF CHAR;
  477.  
  478. BEGIN
  479.  tokenIndex   := 0;
  480.  commentLevel := 0;    (* We don't start out in a comment *)
  481.   
  482.  PerFileInit();
  483.  
  484.  NewPage();
  485.  
  486.  WHILE NOT in.eof DO
  487.   Read( inChar );
  488.  
  489.   (*
  490.    * take action based on value of inChar 
  491.    *)
  492.   IF inChar = HT THEN 
  493.      (* Got a TAB character *)
  494.      PrintChar(' ');
  495.      WHILE (CharCount MOD TabSize) # 0 DO
  496.          (* 
  497.           * The correct working of this loop depends on
  498.           * CharCount being modified by PrintChar.
  499.           *)
  500.          PrintChar(' ');
  501.      END; (* WHILE *)
  502.    ELSIF (inChar = '"') OR (inChar = "'") THEN 
  503.     IF InString THEN 
  504.         IF stringChar = inChar THEN 
  505.         InString := FALSE;
  506.             END; (* IF *)
  507.         ELSIF NOT InComment THEN 
  508.             stringChar := inChar;
  509.                 InString := TRUE;
  510.     END; (* IF *)
  511.         PrintChar( inChar );
  512.  
  513.    ELSIF inChar = '(' THEN  
  514.     PrintChar( inChar );
  515.     Read( inChar );           
  516.     IF inChar = '*' THEN 
  517.         INC( commentLevel );
  518.         InComment := TRUE;
  519.             PrintChar( inChar );
  520.         ELSE Again( in );
  521.         END; (* IF *)
  522.  
  523.    ELSIF inChar = '*' THEN
  524.     PrintChar( inChar );
  525.         IF InComment THEN 
  526.         Read( inChar );
  527.             IF inChar = ')' THEN 
  528.             IF commentLevel > 0 THEN 
  529.             DEC( commentLevel );
  530.         END;
  531.  
  532.         IF commentLevel = 0 THEN 
  533.             InComment := FALSE;
  534.         END; (* IF *)
  535.                 PrintChar( inChar );
  536.             ELSE Again( in );
  537.             END; (* IF *)
  538.         END; (* IF *)
  539.  
  540.    ELSE
  541.     (*
  542.      * Might be a token, check it and print it.
  543.       *)
  544.  
  545.            IF (inChar >= 'A') AND (inChar <= 'Z') THEN 
  546.         (* check for reserved words *)
  547.                 tokenIndex := 0;
  548.                 token[ tokenIndex ] := inChar;
  549.                 INC( tokenIndex );
  550.  
  551.                 IF NOT in.eof THEN 
  552.             LOOP
  553.               Read( inChar );
  554.                       IF in.eof THEN EXIT; END; (* IF *)
  555.                       IF ((inChar < 'A') OR (inChar > 'Z' )) AND
  556.                          ((inChar < 'a') OR (inChar > 'z' )) AND
  557.                          ((inChar < '0') OR (inChar > '9' ))
  558.                       THEN 
  559.                         Again( in );
  560.                         token[ tokenIndex ] := StringTerminator;
  561.                         PrintToken( token, tokenIndex );
  562.                         tokenIndex := 0;
  563.                         EXIT;
  564.                       ELSE
  565.                         token[ tokenIndex ] := inChar;
  566.                         INC( tokenIndex );            
  567.                       END; (* IF *)
  568.                     END; (* LOOP *)
  569.                  END; (* IF *)
  570.            ELSE
  571.               PrintChar( inChar );
  572.            END; (* IF *)
  573.                                                  
  574.   END; (* IF *)
  575.  
  576.  END; (* WHILE *)
  577.  
  578.  (* Form Feed *)
  579.  FinishedFile := TRUE;
  580.  
  581.  FOR i := LineCount TO PageSize DO Write( LF ); END; (* FOR *)
  582.  
  583. END PrintAFile;
  584.  
  585. (* --------------------------------------------------------------------*)
  586.  
  587. PROCEDURE PrintFiles();
  588. BEGIN
  589.  IF ArgIndex <= NumArgs THEN
  590.    WHILE ArgIndex <= NumArgs DO
  591.     GetArgument( ArgIndex, ArgString );
  592.     Lookup( in, ArgString, FALSE );
  593.     in.eof := FALSE;    (* this is to get around a 'bug' in lookup -
  594.              * if you use the same handle when opening
  595.              * and closing several files, eof does not get
  596.              * reset by lookup. If this bug is fixed in your
  597.              * library, you can remove this line.
  598.              *)
  599.     IF in.res # done THEN 
  600.     Terminal.WriteString("Cannot open file ");
  601.         Terminal.WriteString( ArgString );
  602.         Terminal.WriteLn;
  603.     ELSE 
  604.     Terminal.WriteString("Printing ");
  605.     Terminal.WriteString( ArgString );
  606.     Terminal.WriteLn;
  607.     PrintAFile();
  608.     END; (* IF *)
  609.  
  610.     CloseInput();
  611.  
  612.     INC( ArgIndex );
  613.    END; (* WHILE *)
  614.  ELSE (* Use standard input *) 
  615.    PrintAFile();
  616.  END; (* IF *)
  617. END PrintFiles;
  618.  
  619. (* --------------------------------------------------------------------*)
  620.  
  621. PROCEDURE CloseUp();
  622. BEGIN
  623.  
  624.  IF NOT DraftFlag THEN
  625.     (* Set printer in draft mode *)
  626.     Write( CHR(27) );
  627.     Write( CHR(120) );
  628.     Write( CHR(0) );
  629.  END; (* IF *)
  630.  
  631.  CloseOutput();    (* close printer file *)
  632. END CloseUp;
  633.  
  634. (* --------------------------------------------------------------------*)
  635.  
  636. BEGIN (* ModPrint *)
  637.  
  638.  IF GlobalInit() THEN
  639.     IF GetArgs() THEN 
  640.        PrintFiles();
  641.     END; (* IF *)
  642.  END; (* IF *)
  643.  
  644.  CloseUp();
  645. END ModPrint.
  646.